﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using DotNet.DevOps.Tasks.AppConfig;
using DotNet.DevOps.Tasks.Tests.Extensions;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NUnit.Framework;

namespace DotNet.DevOps.Tasks.Tests.Support
{
    [TestFixture, Category("Support")]
    class GenerateSupportFiles
    {
        /// <summary>
        /// This is not a real test but simply a handy autogenerator of std documentation and examples, for support.
        /// </summary>
        [Test]
        public void CreateTargetsFile()
        {
            var tasks = Assembly.GetAssembly(typeof(AppSetting)).GetTypes()
                            .Where(type => typeof(ITask).IsAssignableFrom(type))
                            .Where(type => type.IsPublic)
                            .Where(type => type.IsAbstract == false)
                                .ToList()
                                .OrderBy(task => task.FullName);

            CreateMSBuildTargetsFile(string.Format("{0}.Targets", Assembly.GetAssembly(typeof(AppSetting)).ManifestModule.Name.Replace(".dll", "").Replace(".DLL", "")), tasks);
        }

        private static void CreateMSBuildTargetsFile(string filename, IEnumerable<Type> tasks)
        {
            var xDoc = XDocument.Load(filename.GetPath("Support"));

            tasks.ToList().ForEach(task => xDoc.Root.Add(new XElement(xDoc.Root.Name.Namespace + "UsingTask",
                                                       new XAttribute("AssemblyFile", "$(MSBuildDevOpsTasksLib)"),
                                                       new XAttribute("TaskName", task.FullName))));

            xDoc.Save(filename);
        }

        [Test]
        public void CreateExampleFile()
        {
            var tasks = new List<ITask>();
             Assembly.GetAssembly(typeof (AppSetting)).GetTypes()
                .Where(type => typeof(ITask).IsAssignableFrom(type))
                .Where(type => type.IsPublic)
                .Where(type => type.IsAbstract == false)
                .OrderBy(task => task.FullName)
                .ToList().ForEach(taskType => tasks.Add(Activator.CreateInstance(taskType) as ITask));

            CreateMSBuildExampleFile(string.Format("{0}.Examples.xml", Assembly.GetAssembly(typeof(AppSetting)).ManifestModule.Name.Replace(".dll", "").Replace(".DLL", "")), tasks);
        }

        private static void CreateMSBuildExampleFile(string filename, List<ITask> tasks)
        {
            var xDoc = XDocument.Load(filename.GetPath("Support"));

            var targetNode = xDoc.Root.DescendantNodes().OfType<XElement>()
                                    .Where(baseNode => baseNode.Name.LocalName == "Target").First();

            targetNode.RemoveNodes();

            tasks.ForEach(task => task.SetAllPublicProperties() );

            tasks.ForEach(task => 
                targetNode.Add(new XElement(xDoc.Root.Name.Namespace + task.GetType().Name, GetTaskAttributes(task))));

            xDoc.Save(filename);
        }

        private static object[] GetTaskAttributes(ITask task)
        {
            return
                task.GetPropertiesAsStringNameValuePairs().Select(pair => new XAttribute(pair.Key, pair.Value)).ToArray();
        }
    }
}
